package com.practice.util;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 公平锁
 */
public class FairKeyLock {
    //通过ConcurrentHashMap来保存各个key的锁
    private static final Map<String, ReentrantLock> lock =new ConcurrentHashMap<>();

    /**
     * 通过key来获取ReentrantLock
     * @param key key
     * @return 该key对应的ReentrantLock
     */
    public static ReentrantLock getLock(String key) {
        lock.putIfAbsent(key, new ReentrantLock(Boolean.TRUE));
        return lock.get(key);
    }

    /**
     * 对某个key加同步锁
     * @param key 需要加锁的key
     * @return
     */
    public static void lock(String key) {
        getLock(key).lock();
    }

    /**
     * 对某个key加同步锁
     * @param key 需要加锁的key
     * @return
     */
    public static boolean tryLock(String key) {
        return getLock(key).tryLock();
    }

    /**
     * 对某个key加超时锁
     * @param key 需要加锁的key
     * @param timeout 获取锁的超时时间 超过这个时间则加锁失败
     * @param timeUnit 时间单位 毫秒、秒、分、小时....
     * @return
     */
    public static boolean lockWait(String key, int timeout, TimeUnit timeUnit) {
        ReentrantLock reentrantLock = getLock(key);
        try {
            return reentrantLock.tryLock(timeout, timeUnit);
        } catch (InterruptedException e) {
            //error日志
        }
        return false;
    }

    /**
     * 释放锁
     * @param key 需要释放锁的key
     * @return
     */
    public static void unlock(String key) {
        ReentrantLock reentrantLock = getLock(key);
        if (reentrantLock == null) {
            return;
        }
        reentrantLock.unlock();
    }
}